import csv
import os
import sys
import time
from appfreezeRules import cppProcess
from readFile import ReadFile


class WriteFile(object):
    @staticmethod
    def all_crucial_app(insts):
        c_app_list = []
        for inst in insts:
            if inst.is_crucial_app:
                c_app_list.append(inst.is_crucial_app)
        return ' '.join(set(c_app_list))

    @staticmethod
    def sortInst(file_path):
        listcontents = ReadFile.readFile(file_path, word='appfreeze')
        dic_status = {}
        dic_exception = {}
        dic_testcase = {}
        for contents in listcontents:
            inst = cppProcess(contents)
            print(inst.package_name, inst.path)
            key = (str(inst.basis_so), inst.stringid)
            value = inst
            if inst.package_status:
                if key[0] != "None":
                    if key in dic_status:
                        dic_status[key].append(value)
                    else:
                        dic_status[key] = [value]
                else:
                    key = (inst.package_name + inst.stacktrace + str(inst.can_ignore), inst.stringid)
                    if key in dic_exception:
                        dic_exception[key].append(value)
                    else:
                        dic_exception[key] = [value]
            else:
                if key[0] == "None":
                    key = (inst.package_name + inst.stacktrace + str(inst.can_ignore), inst.stringid)
                if key in dic_testcase:
                    dic_testcase[key].append(value)
                else:
                    dic_testcase[key] = [value]
        dic_total = {**dic_status, **dic_exception}
        return dic_total, dic_testcase

    @staticmethod
    def resText(basis_inst):
        all_info = []
        for basis in basis_inst:
            insts = basis_inst[basis]
            error_so = insts[0].stack
            so_label = '\n'.join(list(set([inst.package_name for inst in insts])))
            if insts[0].all_so_row_list is None:
                valid_fullso = None
            else:
                if insts[0].basis_so:
                    len_sonum = len(insts[0].basis_so)
                    valid_fullso = '\n'.join(insts[0].ori_solist[: len_sonum])
                else:
                    valid_fullso = '\n'.join(insts[0].ori_solist)
            count = len(insts)
            list_files = []
            for inst in insts:
                list_files.append(inst.path)
            all_files = '\n'.join(list_files)
            c_app_str = WriteFile.all_crucial_app(insts)
            if insts[0].foundstatus == 1:
                if len(insts[0].stacktrace.strip()) == 0:
                    error_so = "NOT FOUND"
                else:
                    error_so = 'Stacktrace: at ' + insts[0].stacktrace
                valid_fullso = ''
            elif insts[0].foundstatus == 3:
                error_so = 'Invalid So'
            elif insts[0].foundstatus == 5:
                error_so = 'DFX related'
            elif insts[0].foundstatus in [2, 4]:
                if error_so:
                    if insts[0].stringid:
                        if insts[0].package_name:
                            error_so = f'{insts[0].package_name}由于{insts[0].stringid}卡在{error_so}'
                        else:
                            error_so = f'由于{insts[0].stringid}卡在{error_so}'
                    else:
                        if insts[0].package_name:
                            error_so = f'{insts[0].package_name}卡在{error_so}'
                        else:
                            error_so = f'卡在{error_so}'
                else:
                    error_so = error_so
                if c_app_str:
                    error_so = f'关键应用: {error_so}'
            if insts[0].can_ignore:
                error_so = "IGNORE"
            res_basis = [error_so, so_label, valid_fullso, count, all_files]
            all_info.append(res_basis)
        return all_info

    @staticmethod
    def write(cppdir, basis_inst, testcase=False):
        '''
        comment: write result to txt and csv
        :param cppdir:
        :param basis_inst:
        :return:
        '''
        all_info = WriteFile.resText(basis_inst)
        now = time.strftime('%Y%m%d%H%M%S')
        if testcase:
            txt_file_name = f"TestcaseOfAppfreeze{now}.txt"
            csv_file_name = f"TestcaseOfAppfreeze{now}.csv"
        else:
            txt_file_name = f"ResultOfAppfreeze{now}.txt"
            csv_file_name = f"ResultOfAppfreeze{now}.csv"
        if os.path.isfile(cppdir):
            cppdir = os.path.split(cppdir)[0]
        txt_path = os.path.join(cppdir, txt_file_name)
        csv_path = os.path.join(cppdir, csv_file_name)
        WriteFile.writetxt(txt_path, all_info)
        WriteFile.writecsv(csv_path, all_info)

    @staticmethod
    def writetxt(txt_path, all_info):
        description = [
            '崩溃栈: ',
            'PACKAGE_NAME: ',
            '详情: ',
            '出现次数: ',
            '文件路径: '
        ]
        with open(txt_path, 'w', encoding='utf-8-sig') as fw:
            for cont in all_info:
                if cont is None:
                    fw.write('')
                else:
                    for i in range(len(description)):
                        if cont[i] is not None:
                            so_pri_info = description[i] + str(cont[i])
                            fw.write(so_pri_info + '\n')
                fw.write('\n')
        print('txt_path: ', txt_path)

    @staticmethod
    def writecsv(csv_path, all_info):
        with open(csv_path, "w", newline="", encoding='utf-8-sig') as fcsv:
            writer = csv.writer(fcsv)
            writer.writerow(['崩溃栈', 'PACKAGE_NAME', '详情', '出现次数', '文件路径'])
            for cont in all_info:
                cont[-1] = cont[-1].split('\n')[0]
                writer.writerow(cont)
        fcsv.close()
        print('csv_path: ', csv_path)

    @staticmethod
    def mainOfAppfreeze(file_path):
        sorted_inst, sorted_testcase = WriteFile.sortInst(file_path)
        WriteFile.write(file_path, sorted_inst)
        WriteFile.write(file_path, sorted_testcase, testcase=True)


if __name__ == '__main__':
    argv = sys.argv
    version = 'VERSION: 2023_07_06'
    if len(argv) != 2:  # 判断元素个数
        print("usage: python appfreezeParser.py dir")
    else:
        if argv[1] == '-v':
            print(version)
        else:
            print(version)
            WriteFile.mainOfAppfreeze(argv[1])
